import json
import random
from flask import current_app
import re
from info.models import User
from flask import current_app, session
from flask import make_response, jsonify

from info import redis_store, db
from info.libs.yuntongxun.sms import CCP
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
from . import passport_blue
from flask import request
from datetime import  datetime

"""
退出登陆
请求路径:/passport/logout
请求方式: POST
请求参数: 无
返回值: errno errmsg
注意点: 使用session.pop()来清除session数据
"""
@passport_blue.route('/logout', methods=["POST"])
def logout():
    # 消除session信息/ 消除状态保持
    # 退出就是就将登陆时保存的信息使用pop弹出
    session.pop('user_id', None)
    session.pop("nick_name", None)
    # 返回状态
    return jsonify(errno=RET.OK, errmsg="退出用户")
    # 记录最后登陆时间


"""
登陆用户
1. 请求路径: /passport前缀/login路径
2. 请求方式: POST
3. 请求参数: mobile, password
4. 返回值: errno, errmsg
注意点 效验密码正确性的时候使用的是check_password_hash
"""
@passport_blue.route('/login', methods=['POST'])
def login():
    # 1, 获取参数
    mobile = request.json.get("mobile")
    password = request.json.get("password")
    # 2. 效验参数
    # 根据手机号,获取用户对象,判断是否存在
    try:
        user = User.query.filter(User.mobile == mobile).first()  # 比对手机号
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询用户失败")
    if not user:
        return jsonify(errno=RET.NODATA, errmsg='该用户不存在')
    # 判断密码是否正确
    if not user.check_passowrd(password):
        return jsonify(errno=RET.DATAERR, errmsg="密码错误")

    # 3. 状态保持(session)
    session["user_id"] = user.id     # 用户id
    session["nick_name"] = user.nick_name  # 用户姓名

    # 记录最后登陆时间
    # try:
    #     user.last_login = datetime.now()  # 获取当前系统时间
    #     db.session.commit()
    # except Exception as e:
    #     current_app.logger.error(e)
    user.last_login = datetime.now()  # 每当视图函数结束时会获取系统时间,然后自动提交
    # 4. 返回响应
    return jsonify(errno=RET.OK, errmsg="登陆成功")

# 请求路径:/passport/接口
# 请求方式: GET
# 请求参数: cur_id, pre_id
# 返回值: 图片或者图片验证码

"""
1. 注册用户
2. 请求路径: /passport/register
3. 请求参数: mobile, sms_code, password
4. 返回值: errno, errmsg
"""
@passport_blue.route('/register', methods=['POST'])
def register():
    # 1 获取参数
    # json_data = request.data    #  将json 数据转字典
    # dict_data = json.loads(json_data)
    # 通过ajxa提交的请求都是使用requst.data获取
    dict_data = request.json  # 或者是使用dict_data = request.git_json()
    # 这两句的内部执行方法是一样的 所以作用一样 并且可以代替上面两句代码 实现同样的功能

    #  获取前端提交过来的参数
    mobile = dict_data.get('mobile')  # 手机号
    sms_code = dict_data.get('sms_code')  # 短信验证码
    password = dict_data.get('password')   # 密码

    # 2 校验参数
    # 判断用户是否存在
    count = User.query.filter(User.mobile == mobile).count()
    if count > 0:
         return jsonify(errno=RET.DATAERR, errmsg="用户已存在")

    # 短信验证码正确性
    redis_sms_code = redis_store.get("sms_code:%s" % mobile)
    if not redis_sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码过期")
    if sms_code != redis_sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码错误")
    # 3 创建用户对象,数据入库
    try:
        user = User()
        user.nick_name = mobile  # 默认名称
        user.password = password  # 密码
        user.mobile = mobile  # 手机号

        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="注册失败")
    # 4返回响应
    return jsonify(errno=RET.OK, errmsg="注册成功")

"""
思路: 1. 编写获取图片验证码的接口
     2. 前端第一次展示注册页面,以及每次点击图片的时候,会向后端接口发送获取图片请求
"""
@passport_blue.route('/image_code')
def image_code():

    # 1. 获取参数.cui_id  --编号
    cur_id = request.args.get("cur_id")  # 存储当前的验证码图片编号
    pre_id = request.args.get("pre_id")  # 存储上一个验证码图片编号

    # 2. 效验参数
    if not cur_id:
        return "参数不全"

    # 2.1 判断上一个验证码图片编号是否存在,存在则删除
    if pre_id:
        redis_store.delete("image_code:%s" % pre_id)
        # delete 删除 删除kye就可以删除值

    # 3. 生成图片验证码
    name, text, image_code = captcha.generate_captcha()
    # 调用captcha里的generate_captcha方法,获得三个参数 分别是图片验证的名字,验证码,图片
    print(type(image_code))

    current_app.logger.debug('image_code---%s' % text)

    # 4. 存储到redis中
    redis_store.set("image_code:%s" % cur_id, text, 300)
    # 前缀:验证码图片, 验证码的值, 有效期

    response = make_response(image_code)
    # make_response 生成一个响应体对象,可以将响应头修改
    response.headers['Content-Type'] = 'image/png'
    # 指定浏览器解析数据的类型--接收image_code后就会按照指定的格式解析

    # 5 返回图片验证码/图片
    return image_code
    # 返回图片

"""
获取短信验证码
请求路径/passport/sms_code   --- 前缀/路径名称
请求方式 : POST
请求参数 : mobile, image_code, image_code_id ----手机号, 图片验证码, 验证码编号
返回值 : errno , errmsg   ---状态
效验验证参数

"""
@passport_blue.route('/sms_code', methods=['POST'])
def sms_code():
    print("注册")
    # 1.获取参数
    json_data = request.data   # ajax请求方式需要用.data获取数据,获取的是json格式的数据
    dict_data = json.loads(json_data.decode())  # 将json格式的数据转换成字典格式, 使用loads
    mobile = dict_data.get("mobile")
    image_code = dict_data.get("image_code")   # 字典取值  get("键名")  get方法的特点是就算没有数据也不会报错
    image_code_id = dict_data.get("image_code_id")
    # 2. 效验参数
    if not all([mobile, image_code, image_code_id]):
        # all 是判断所有的数据都条件成立时会返回True   效验是否有空值
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全 ')

    # 校验手机格式以及图片验证码正确性
    if not re.match(r'1[3-9]\d{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmas="手机号格式错误")
    #           参数错误就返回errmas

    # 判断图片验证码正确性---image_code/前缀%s % image_code_id/编号
    redis_image_code = redis_store.get('image_code:%s' % image_code_id)
    if not redis_image_code:
        # 判断图片验证码是否过期  若是过期则图片验证码会消失
        return jsonify(errno=RET.PARAMERR, errmsg='图片验证码过期')
    redis_store.delete("imgage_code:%s" % image_code_id)
    # 图片验证码只能使用一次,所以使用过后就将图片验证码编号删除

    # 对比验证码
    if image_code.lower() != redis_image_code.lower():
        # lower()  方法 将数据字符串转换成小写
        return jsonify(errno=RET.DATAERR, errmsg='图片验证码错误')

    # 3. 发送短信,数据入库
    # ccp = CCP()
    sms_code = "%06d" % random.randint(0, 999999)  # 使用random模块获得一个随机数  使用%06d格式获得一个限制为6位数的数字
    # result = ccp.send_template_sms(mobile, [sms_code, 5], 1)
    # # 使用云通讯模块CPP对象,调用send_template_sms方法 传入参数
    # if result == -1:
    #     return jsonify(errno=RET.THIRDERR, errmsg="短信发送失败")
    print(sms_code)
    current_app.logger.debug("sms_code = %s" % sms_code)
    # jsonify方法将字典转化成json格式后返回到页面显示

    redis_store.set("sms_code:%s" % mobile, sms_code, 300)
    # redis_store.set(手机号, 随机短信验证码, 有效期)
    # 入库是为了将验证码保存起来用于与生成的验证码进行比对

    # 4. 返回响应
    return jsonify(errno=RET.OK, errmsg="发送成功")